package util;

import com.google.zxing.*;
import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.common.HybridBinarizer;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;

import javax.imageio.ImageIO;
import java.io.*;
import java.util.Map;

public class QRcodeUtils {
    /**
     * 实际使用过程中，data, path, charset,
     * map 通常是作为用户初始就要指定的与图片
     * 数据相关的参数，故作为构造方法需要初始就
     * 传入的参数。
     * */
    private String data;
    private String path;
    private String charset;
    private Map<EncodeHintType, ErrorCorrectionLevel> map;

    public QRcodeUtils(String data, String path, String charset, Map<EncodeHintType, ErrorCorrectionLevel> map) {
        this.data = data;
        this.path = path;
        this.charset = charset;
        this.map = map;
    }

    public void makeQRcode(int height, int width) throws IOException, WriterException {
        // BitMatrix 是一个二位位矩阵类，用于存信息。 MultiFormatWriter 是工厂类，自动寻找合适的类编码数据。
        BitMatrix bitMatrix = new MultiFormatWriter().encode(new String(data.getBytes(charset), charset),
                                                             BarcodeFormat.QR_CODE,
                                                             width, height);

        // 将位矩阵信息转为图片。
        MatrixToImageWriter.writeToFile(bitMatrix, path.substring(path.lastIndexOf('.')+1), new File(path));
    }

    // 考虑到读取的普遍性，可以直接作为一个静态类，这样在调用时就可以不用创建该类的实例了。
    public static String readQRcode(String path) throws IOException, NotFoundException {
        // BinaryBitmap 是核心位图类，可传入 Reader 中解码。 Binarizer 提供了一系列方法将亮度信息转化为位图信息
        BinaryBitmap binaryBitmap = new BinaryBitmap(new HybridBinarizer(
                new BufferedImageLuminanceSource(
                        ImageIO.read(new FileInputStream(path))
                )
        ));

        // MultiFormatReader 是工厂类，自动寻找合适的类解码数据
        Result result = new MultiFormatReader().decode(binaryBitmap);
        return result.getText();
    }
}
